import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
from mpl_toolkits.mplot3d import Axes3D

"""
利用matplotlib画图使用,请在python3控制台输入该文件的代码
"""
dir_file = "D:/PyCharmProjects/MainProjects/anaconda-numpy/降维/data/railway_okzhuanginfo_delTail_token.csv"
train = pd.read_csv(dir_file)
y = None
if dir_file[-9:-4] == 'token':
    y = train['y']
    train.drop('y', axis=1)

# 删掉指定的非数据列
train = train.drop(['id', 'ZhuangNum', 'ProjectID', 'Starttime', 'Endtime', 'DeviceNum', 'State'], axis=1)
train.head(3)

# 检查每个变量中缺失值的百分比。若不为0，则有缺失
a = train.isnull().sum() / len(train) * 100

# 在变量中保存小于阈值的列名
variables = train.columns
variable = []
for i in range(0, len(variables)):
    if a[i] <= 20:  # 设置阈值为20%,小于20的保留
        variable.append(variables[i])

# 低方差滤波（Low Variance Filter）
'''
如果我们有一个数据集，其中某列的数值基本一致，也就是它的方差非常低，那么这个变量还有价值吗？
和上一种方法的思路一致，我们通常认为低方差变量携带的信息量也很少，所以可以把它直接删除。
放到实践中，就是先计算所有变量的方差大小，然后删去其中最小的几个。
需要注意的一点是：方差与数据范围相关的，因此在采用该方法前需要对数据做归一化处理。
'''
# 放在示例中，我们先填上缺失值：
'''
让我们首先使用已知 Upspeed 观测值的中值来估算 Upspeed 列中的缺失值。
对于 Incurrent 列，我们将使用已知 Incurrent 值的众数来估算缺失值：
'''
train['Upspeed'].fillna(train['Upspeed'].median(), inplace=True)
train['DownSpeed'].fillna(train['DownSpeed'].median(), inplace=True)
train['Incurrent'].fillna(train['Incurrent'].mode()[0], inplace=True)
train['OutCurrent'].fillna(train['OutCurrent'].mode()[0], inplace=True)

# 检查缺失值是否已经被填充：
train.isnull().sum() / len(train) * 100

# 再计算所有数值变量的方差：
train.var()  # 此时获得高相关变量 OutCurrent (最高方差)

# 如上图所示，和其他变量相比，Lon的方差非常小，因此可以把它直接删除。
numeric = train
var = numeric.var()
numeric = numeric.columns
need_drop_col = []

for i in range(0, len(var)):
    if var[i] < 10:  # 将阈值设置为10％
        need_drop_col.append(numeric[i])

print(need_drop_col)

train.drop(need_drop_col, axis=1, inplace=True)

train.corr()

from sklearn import preprocessing

# Z-Score标准化
# 建立StandardScaler对象
zscore = preprocessing.StandardScaler()
# 标准化处理
df_zs = zscore.fit_transform(train)
df = train.values

# %% == PCA ================================================================
from sklearn.decomposition import PCA

t1 = time.time()
n_components = 3
pca = PCA(n_components=n_components)
pca_fit = pca.fit(df_zs)  # 再通过 pca_fit.transform([[...一个7列的二维数组...]])
pca_result = pca_fit.transform(df_zs)

'''
在这种情况下，n_components将决定转换数据中主成分的数量。让我们想象一下使用这 3 个组件解释了多少差异。
我们将使用explained_variance_ratio_来计算相同的值。
上面的红色线说明了一共有多少方差可以被解释
下面的蓝线表示每组数据解释了多少方差(从0开始,整数点的数据)
'''
plt.plot(range(n_components), pca.explained_variance_ratio_)
plt.plot(range(n_components), np.cumsum(pca.explained_variance_ratio_))
plt.title("component-wise and cumulative explained variance")  # 组件方式和累积解释方差
plt.show()

print("PCA 耗时: %.2f s" % (time.time() - t1))    # 0.25s

# 导出数据
from util import operate_csv, draw_func_equation

draw_func_equation.plot_embedding_3d(pca_result, y)

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection='3d')
for i in range(pca_result.shape[0]):
    ax.text(pca_result[i, 0], pca_result[i, 1], pca_result[i, 2], str(y[i]), color=plt.cm.Set1(y[i])
            , fontdict={'weight': 'bold', 'size': 9})

ax.set_xlabel('X')
ax.set_xlim(-3, 3)  # 拉开坐标轴范围显示投影
ax.set_ylabel('Y')
ax.set_ylim(-3, 3)
ax.set_zlabel('Z')
ax.set_zlim(-3, 3)
plt.show()
